/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2025-03-27 14:57:56
 * @LastEditTime : 2025-08-22 15:58:48
 * @FilePath     : \GD32F407-DEMO\hal_driver\ll_gpio.h
 * @Description  : gpio低层驱动
 * @Version      : V1.0
 * @History      :
 * @Note         :
 */

#ifndef __ll_gpio_H__
#define __ll_gpio_H__

/***************************************Includes***********************************/
#include <stdint.h>

#if defined(GD32F407)
#include "gd32f4xx.h"
#elif defined(STM32F40_41xxx)
#include "stm32f4xx.h"
#elif defined(GD32F10X_HD)
#include "gd32f10x.h"
#elif defined(STM32F10X_HD)
#include "stm32f10x.h"
#elif defined(PY32F071xB)
#include "py32f0xx.h"
#else
#error "No device selected"
#endif

/*************************************Public Macros********************************/
// #define

typedef enum {
    GPIO_LL_MODE_INPUT,  // 输入
    GPIO_LL_MODE_OUTPUT, // 输出
    GPIO_LL_MODE_AF,     // 复用
    GPIO_LL_MODE_ANALOG, // 模拟
} gpio_ll_mode_t;

typedef enum {
    GPIO_LL_OTYPE_PP, // 推挽
    GPIO_LL_OTYPE_OD, // 开漏
} gpio_ll_outtype_t;

typedef enum {
    GPIO_LL_PULL_NO,
    GPIO_LL_PULL_UP,
    GPIO_LL_PULL_DOWN,
} gpio_ll_pull_t;

typedef enum {
    GPIO_LL_SPEED_LOW,
    GPIO_LL_SPEED_MEDIUM,
    GPIO_LL_SPEED_HIGH,
    GPIO_LL_SPEED_VERY_HIGH,
} gpio_ll_speed_t;

/***********************************Public Statement*******************************/

typedef struct {
    uint32_t port;
    uint32_t pin;
    uint32_t mode;
    uint32_t otype;
    uint32_t pull;
    uint32_t speed;
    uint32_t af_num;
} gpio_ll_t;

/***********************************Public Functions*******************************/

/**
 * @brief gpio初始化
 * @param  gpio
 * @param  port             端口
 * @param  pinnum           管脚
 * @param  mode             输入输出模式
 * @param  pull             上下拉
 * @param  speed            速度
 * @param  af_num           复用号 仅复用模式可用
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_init(
    gpio_ll_t *gpio,
    uint32_t port,
    uint32_t pinnum,
    gpio_ll_mode_t mode,
    gpio_ll_outtype_t otype,
    gpio_ll_pull_t pull,
    gpio_ll_speed_t speed,
    uint32_t af_num);

/**
 * @brief gpio反初始化
 * @param  gpio
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_deinit(gpio_ll_t *gpio);
// /**
//  * @brief 设置gpio模式
//  * @param  gpio
//  * @param  mode
//  * @return int 0成功 -1失败
//  * @note null
//  */
// int gpio_ll_set_mode(gpio_ll_t *gpio, gpio_ll_mode_t mode);
/**
 * @brief 设置输出类型
 * @param  gpio
 * @param  otype
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_set_outtype(gpio_ll_t *gpio, gpio_ll_outtype_t otype);
/**
 * @brief 设置上下拉电阻
 * @param  gpio
 * @param  pull
 * @return int 0成功 -1失败
 * @note null
 */
int gpio_ll_set_pull(gpio_ll_t *gpio, gpio_ll_pull_t pull);
/**
 * @brief 设置gpio速度
 * @param  gpio
 * @param  speed
 * @return int 0成 -1失败
 * @note null
 */
int gpio_ll_set_speed(gpio_ll_t *gpio, gpio_ll_speed_t speed);


/**
 * @brief 设置gpio模式
 * @param  gpio
 * @param  mode
 * @return int 0成功 -1失败
 * @note null
 */
static inline int gpio_ll_set_mode(gpio_ll_t *gpio, gpio_ll_mode_t mode) {
    // clang-format off
#if defined(GD32F407)
    switch (mode) {
    case GPIO_LL_MODE_INPUT: gpio->mode = GPIO_MODE_INPUT; break;
    case GPIO_LL_MODE_OUTPUT: gpio->mode = GPIO_MODE_OUTPUT; break;
    case GPIO_LL_MODE_AF: gpio->mode = GPIO_MODE_AF; gpio_af_set(gpio->port, gpio->af_num, gpio->pin); break;
    case GPIO_LL_MODE_ANALOG: gpio->mode = GPIO_MODE_ANALOG; break;
    default: gpio->mode = GPIO_MODE_INPUT; break;
    }
    gpio_mode_set(gpio->port, gpio->mode, gpio->pull, gpio->pin);
    return 0;
#elif defined(GD32F10X_HD)
    gpio->mode = mode;
    if (mode == GPIO_LL_MODE_INPUT) {
        switch (gpio->pull) {
            case GPIO_LL_PULL_NO: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_UP: gpio_init(gpio->port, GPIO_MODE_IPU, gpio->speed, gpio->pin); break;
            case GPIO_LL_PULL_DOWN: gpio_init(gpio->port, GPIO_MODE_IPD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_IN_FLOATING, gpio->speed, gpio->pin); break;
        }
    } else if (mode == GPIO_LL_MODE_OUTPUT){
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_OUT_PP, gpio->speed, gpio->pin); break;
            case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
            default: gpio_init(gpio->port, GPIO_MODE_OUT_OD, gpio->speed, gpio->pin); break;
        }
    } else if (mode == GPIO_LL_MODE_ANALOG) {
        gpio_init(gpio->port, GPIO_MODE_AIN, gpio->speed, gpio->pin);
    } else if (mode == GPIO_LL_MODE_AF) {
        rcu_periph_clock_enable(RCU_AF);
        switch (gpio->otype) {
        case GPIO_LL_OTYPE_OD: gpio_init(gpio->port, GPIO_MODE_AF_OD, gpio->speed, gpio->pin); break;
        case GPIO_LL_OTYPE_PP: gpio_init(gpio->port, GPIO_MODE_AF_PP, gpio->speed, gpio->pin); break;
        default: return -1;
        }
    }
    return 0;
#elif defined(STM32F40_41xxx)
uint32_t af_source;
    switch (mode) {
        case GPIO_LL_MODE_INPUT: gpio->mode = GPIO_Mode_IN; break;
        case GPIO_LL_MODE_OUTPUT: gpio->mode = GPIO_Mode_OUT; break;
        case GPIO_LL_MODE_AF: gpio->mode = GPIO_Mode_AF; break;
        case GPIO_LL_MODE_ANALOG: gpio->mode = GPIO_Mode_AN; break;
        default: gpio->mode = GPIO_Mode_IN; break;
    }
    if (mode == GPIO_LL_MODE_AF) {
        switch (gpio->pin) {
            case GPIO_Pin_0: af_source = GPIO_PinSource0; break;
            case GPIO_Pin_1: af_source = GPIO_PinSource1; break;
            case GPIO_Pin_2: af_source = GPIO_PinSource2; break;
            case GPIO_Pin_3: af_source = GPIO_PinSource3; break;
            case GPIO_Pin_4: af_source = GPIO_PinSource4; break;
            case GPIO_Pin_5: af_source = GPIO_PinSource5; break;
            case GPIO_Pin_6: af_source = GPIO_PinSource6; break;
            case GPIO_Pin_7: af_source = GPIO_PinSource7; break;
            case GPIO_Pin_8: af_source = GPIO_PinSource8; break;
            case GPIO_Pin_9: af_source = GPIO_PinSource9; break;
            case GPIO_Pin_10: af_source = GPIO_PinSource10; break;
            case GPIO_Pin_11: af_source = GPIO_PinSource11; break;
            case GPIO_Pin_12: af_source = GPIO_PinSource12; break;
            case GPIO_Pin_13: af_source = GPIO_PinSource13; break;
            case GPIO_Pin_14: af_source = GPIO_PinSource14; break;
            case GPIO_Pin_15: af_source = GPIO_PinSource15; break;
            default: return -1; break;
        }
        GPIO_PinAFConfig((void *)gpio->port, af_source, gpio->af_num);
    }
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio_cfg.GPIO_Mode = gpio->mode;
    gpio_cfg.GPIO_OType = gpio->otype;
    gpio_cfg.GPIO_PuPd = gpio->pull;
    gpio_cfg.GPIO_Speed = gpio->speed;
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(STM32F10X_HD)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Speed = gpio->speed;
    gpio_cfg.GPIO_Pin = gpio->pin;
    gpio->mode = mode;
    if (mode == GPIO_LL_MODE_INPUT) {
        switch (gpio->pull) {
            case GPIO_LL_PULL_NO: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
            case GPIO_LL_PULL_UP: gpio_cfg.GPIO_Mode = GPIO_Mode_IPU; break;
            case GPIO_LL_PULL_DOWN: gpio_cfg.GPIO_Mode = GPIO_Mode_IPD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING; break;
        }
    } else if (mode == GPIO_LL_MODE_OUTPUT){
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    } else if (mode == GPIO_LL_MODE_ANALOG) {
        gpio_cfg.GPIO_Mode = GPIO_Mode_AIN;
    } else if (mode == GPIO_LL_MODE_AF) {
        switch (gpio->otype) {
            case GPIO_LL_OTYPE_PP: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_PP; break;
            case GPIO_LL_OTYPE_OD: gpio_cfg.GPIO_Mode = GPIO_Mode_AF_OD; break;
            default: gpio_cfg.GPIO_Mode = GPIO_Mode_Out_OD; break;
        }
    }
    GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#elif defined(PY32F071xB)
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.Pin = gpio->pin;
    gpio_cfg.Pull = gpio->pull;
    gpio_cfg.Speed = gpio->speed;
    gpio_cfg.Alternate = gpio->af_num;
    switch (mode) {
    case GPIO_LL_MODE_INPUT: gpio_cfg.Mode = GPIO_MODE_INPUT; break;
    case GPIO_LL_MODE_OUTPUT: gpio_cfg.Mode = gpio->otype == GPIO_LL_OTYPE_OD ? GPIO_MODE_OUTPUT_OD : GPIO_MODE_OUTPUT_PP; break;
    case GPIO_LL_MODE_ANALOG: gpio_cfg.Mode = GPIO_MODE_ANALOG; break;
    case GPIO_LL_MODE_AF: gpio_cfg.Mode = gpio->otype == GPIO_LL_OTYPE_OD ? GPIO_MODE_AF_OD : GPIO_MODE_AF_PP; break;
    default: return -1;
    }
    gpio->mode = gpio_cfg.Mode;
    HAL_GPIO_Init((void *)gpio->port, &gpio_cfg);
    return 0;
#endif
    return -1;
    // clang-format on
}

/**
 * @brief 设置输出
 * @param  gpio
 * @param  output
 * @return int 0成功 -1失败
 * @note null
 */
static inline int gpio_ll_set_output(gpio_ll_t *gpio, uint32_t output) {
#if defined(GD32F407) || defined(GD32F10X_HD)
    gpio_bit_write(gpio->port, gpio->pin, output ? 1 : 0);
    return 0;
#elif defined(STM32F40_41xxx) || defined(STM32F10X_HD)
    GPIO_WriteBit((void *)gpio->port, gpio->pin, output ? 1 : 0);
#elif defined(PY32F071xB)
    HAL_GPIO_WritePin((void *)gpio->port, gpio->pin, output ? GPIO_PIN_SET:GPIO_PIN_RESET);
#endif
    return -1;
}
/**
 * @brief 获取输入
 * @param  gpio
 * @return int 0低电平 1高电平
 * @note null
 */
static inline int gpio_ll_get_input(gpio_ll_t *gpio) {
#if defined(GD32F407) || defined(GD32F10X_HD)
    return gpio_input_bit_get(gpio->port, gpio->pin);
#elif defined(STM32F40_41xxx) || defined(STM32F10X_HD)
    return GPIO_ReadInputDataBit((void *)gpio->port, gpio->pin);
#elif defined(PY32F071xB)
    return HAL_GPIO_ReadPin((void *)gpio->port, gpio->pin);
#endif
    return -1;
}

/***************************************Public Variables**********************************/


#endif
/* [] END OF FILE */
